#include "app.h"
#include "utils.h"
#include "cli.h"

static int prompt_ProcessCommand(void);
static int prompt_Beep(int argc, portCHAR **argv);
static int prompt_Relay(int argc, portCHAR **argv);
static int prompt_ClearTicks(int argc, portCHAR **argv);
static int prompt_Dump (int argc, portCHAR **argv);
static int prompt_OffSet (int argc, portCHAR **argv);
static int prompt_ZeroAdjustment (int argc, portCHAR **argv);
static int prompt_Weight (int argc, portCHAR **argv);
static int prompt_STS(int argc, portCHAR **argv);

// ###############################################################################################
// LISTA DOS COMANDOS A SER CHAMADOS PELO CLI

static const tCLI cli_list [] = {
	{ "help",
  			0,  0,
  			CMD_TYPE_FUNCTION, { cli_Help },
  			"Displays this help list", NULL },

	{ "beep",
			1,  1,
  			CMD_TYPE_FUNCTION,  { prompt_Beep },
  			"Play beep sound", "beep <mode: 0(off) at 6>" },

	{ "relay",
  			2,  3,
  			CMD_TYPE_FUNCTION,  { prompt_Relay },
  			"Turn on or off determined relay", "realy <1/2> <on/off> <timeout in secs (OPT)>" },

	{ "dump",
  			2,  2, CMD_TYPE_FUNCTION,  	{ prompt_Dump },
  			"Dump memory",
  			"dump <addr> <size>" },

	{ "clear_ticks",
			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_ClearTicks },
  			"Clear counter ticks system", NULL },

	{ "offset",
  			1,  1,
  			CMD_TYPE_FUNCTION,  { prompt_OffSet },
  			"Adjusts the balance offset", 	NULL },

	{ "zero",
  			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_ZeroAdjustment },
  			"Adjusts the weight reading to zero when there is nothing on the balance", 	NULL },

	{ "weight",
  			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_Weight },
  			"Weight reading in grams", 	NULL },

	{ "sts",
  			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_STS },
  			"Shows all status of the ", 	NULL },

	{ NULL, 0,  0, CMD_TYPE_FUNCTION,  	{ NULL },
			NULL,
			NULL },
};

void prompt_Process(void) {
	static int resuslt;
	resuslt = prompt_ProcessCommand();
	switch (resuslt) {
	case errCLI_EXED_ARGS:
		lprintf("System error"CMD_TERMINATOR);
		break;
	case errCLI_CMD_NOT_FOUND:
		lprintf("Unknown command"CMD_TERMINATOR);
    	break;
    case pdFAIL:
    	lprintf("Error in executing the command"CMD_TERMINATOR);
    	break;
    }
}

static int result_prompt;
static u8 buffer_prompt[CLI_CMD_BUFFER_SIZE];
static portCHAR *argv_prompt [CLI_N_ARGS];
static int argc_prompt;

static int prompt_ProcessCommand(void) {
	// CAPTURA COMANDOS DO TERMINAL. SE TECLOU ENTER A FUNÇÃO RETORNA COM A QUANTIDADE DE CHAR DO COMANDO
	result_prompt = cli_GetLine (buffer_prompt, sizeof (buffer_prompt), PROMPT); // Chamo o console para entrada de comandos

	// CHECA FOI ENTRADO COM O COMANDO
	if (result_prompt) {	// checa se há entrada de comandos
   		if (cli_ArgsParse ((char *) buffer_prompt, argv_prompt, sizeof (argv_prompt), &argc_prompt) == errCLI_EXED_ARGS) // Captura os endereços iniciais de cada argumento, contidos no comando, e grava nas posições do argv
   			result_prompt = errCLI_EXED_ARGS;
   		else if (argv_prompt[0])
   			result_prompt = cli_ArgsDispatch(cli_list, argc_prompt, &argv_prompt[0]);							// Executa a função referente ao comando digitado
  	} else result_prompt = pdPASS;

	return result_prompt;
}

static int prompt_Beep(int argc __attribute__ ((unused)), portCHAR **argv) {
	long p1;
	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	beep_Play(p1);
	return pdPASS;
}

static int prompt_Relay(int argc __attribute__ ((unused)), portCHAR **argv ) {
	long p1=0, p2=0, p3=0;

	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	if (strcmp(argv[1], "on") == 0) p2=pdON; else p2=pdOFF;
	if (argc > 2) { if (!xatoi(&argv[2], &p3)) return pdFAIL; }

	int ret = relay_Set(p1-1, p2, p3);

	if (ret == errDEVICE_NOT_FOUND)
		lprintf("ERROR: relay must be 1 or 2"CMD_TERMINATOR);

	return pdPASS;
}

static int prompt_ClearTicks(int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	control.ticks = 0;
	return pdPASS;
}

static int prompt_Dump (int argc __attribute__ ((unused)), portCHAR **argv ) {
	long p1, p2;

	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	if (!xatoi(&argv[1], &p2)) return pdFAIL;

	if (p1 < 0) p1 = 0;
	if (p2 < 1) p2 = 256;

	u8 *ptr = (u8*) p1;
	u16 qtd_rd = p2;

	while (qtd_rd) {
  		if (qtd_rd >= 16)
  			// Enquanto o qtd_rd for maior que 15 faz, depois incrementea addr do buffer e da eeprom por 16, e decrementa qtd_rd por 16
  			for( ; qtd_rd>=16; ptr+=16, p1+=16, qtd_rd-=16 )
  				put_dump16(ptr, p1, 16, 16);

		if (qtd_rd)
			put_dump16(ptr, p1, qtd_rd, 16);
  	}

	return pdPASS;
}

static int prompt_OffSet (int argc __attribute__ ((unused)), portCHAR **argv) {
	long p1;

	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	hx711_SetOffSet(p1);
	return pdPASS;
}

static int prompt_ZeroAdjustment (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	lprintf("Making zero adjustment"CMD_TERMINATOR);
	lprintf("wait..."CMD_TERMINATOR);
	if (hx711_ZeroAdjustment()) lprintf("ok"CMD_TERMINATOR); else lprintf("ERRO"CMD_TERMINATOR);
	return pdPASS;
}

static int prompt_Weight (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	s32 val;
	hx711_GetValue(&val);
	lprintf("%dgr"CMD_TERMINATOR, val);
	return pdPASS;
}

#include "hx711_drv.h"
static int prompt_STS(int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	lprintf(CMD_TERMINATOR);
	lprintf(CMD_TERMINATOR);
	lprintf("SYSTEM"CMD_TERMINATOR);
	lprintf("    "PROGAM_NAME);
	lprintf("    ucLibc version "__VERSION CMD_TERMINATOR);
	lprintf("    count TICKS: %u"CMD_TERMINATOR, control.ticks);
	lprintf("    key pressing: %u"CMD_TERMINATOR, control.key);
	lprintf(CMD_TERMINATOR);

	lprintf(CMD_TERMINATOR);
	lprintf("HX711"CMD_TERMINATOR);
	lprintf("    offset: %d"CMD_TERMINATOR, hx711_GetOffSet());
	lprintf("    scale: %f"CMD_TERMINATOR, hx711_GetScale());
	s32 val;
	hx711_GetValue(&val);
	lprintf("    weight: %dgr"CMD_TERMINATOR, val);

	return pdPASS;
}
